using UnityEngine;
using System.Collections;
using System.IO;
using System.Diagnostics;

public class mapGenerationScript : MonoBehaviour {
    private GameObject referenceAttract;

    // Use this for initialization
    void Start()
    {
        referenceAttract = GameObject.Find("attract");
        if (referenceAttract == null)
        {
            throw new System.Exception("Reference attract not found");
        }
    }

    public MidiSequence[] parseMidiFolder()
    {
        DirectoryInfo info = new DirectoryInfo(GeneralParameters.songsDirectory);
        FileInfo[] files = info.GetFiles("*.mid");
        MidiSequence[] midiSequences = new MidiSequence[files.Length];
        for (int i = 0; i < files.Length; i++)
        {
            string fileName = files[i].Name;
            string tmidPath = midiToText(fileName);
            MidiSequence midiSequence = new MidiSequence();
            midiSequences[i] = midiSequence.parse(tmidPath);
        }
        return midiSequences;
    }

    public string midiToText(string midiFileName)
    {
        string tmidFileName = midiFileName.Replace(".mid", ".tmid");

        DirectoryInfo info = new DirectoryInfo(GeneralParameters.songsDirectory);
        if (info.GetFiles(tmidFileName).Length == 0)
        {
            if (GeneralParameters.debug) print("convert midi file " + midiFileName + " to " + tmidFileName);
            //string args = "\"" + midiFileName + "\" " + midiFileName.Replace(".mid", ".tmid") + "\"";
            string args = "\"" + midiFileName + "\" \"" + tmidFileName + "\"";
            ProcessStartInfo startinfos = new ProcessStartInfo();
            startinfos.WorkingDirectory = GeneralParameters.songsDirectory;
            startinfos.FileName = "midiToText.exe";
            startinfos.Arguments = args;
            Process.Start(startinfos);
            System.Threading.Thread.Sleep(1000);
            File.Delete(GeneralParameters.songsDirectory + "\\cv.html");
            File.Delete(GeneralParameters.songsDirectory + "\\hFunc.txt");
        }

        return GeneralParameters.songsDirectory + "\\" + tmidFileName;
    }

    public void generateAttracts(MidiSequence midiSequence)
    {
        if (GeneralParameters.debug) print("generate level");

        if (GeneralParameters.debug) print("Recovery track number " + GeneralParameters.numTrack);
        Hashtable track = (Hashtable)midiSequence.tracks[GeneralParameters.numTrack];

        if (GeneralParameters.debug) print("Recovery notes of the track");
        ArrayList notes = (ArrayList)track["notes"];
        int lastIndex = notes.Count;
        if (GeneralParameters.debug) print(lastIndex + " notes recovered");

        if (GeneralParameters.maxNbNotes + GeneralParameters.firstNote < lastIndex)
            lastIndex = GeneralParameters.maxNbNotes + GeneralParameters.firstNote;
        if (GeneralParameters.debug) print("First note = " + GeneralParameters.firstNote + " ; Last note = " + (lastIndex - 1));

        GameObject currentAttract = referenceAttract;
        int index = GeneralParameters.firstNote;
        float currentTime = -1f;
        int i = 0;
        while (index < lastIndex)
        {
            Note note = (Note)notes[i];
            float time = note.startTime;
            if (GeneralParameters.debug) print("generateAttract > step=" + index + "/" + lastIndex + " i=" + i + " t=" + currentTime + " note.startTime=" + time);

            if (midiSequence.tempo.ContainsKey(note.startTime))
            {
                changeTempo((int)midiSequence.tempo[note.startTime]);
            }
            if (time > currentTime)
            {
                currentAttract = createAttractFromNote(note, index, currentAttract);
                currentTime = time;
                
                index++;
            }
            else
            {
                if(GeneralParameters.onPartition)
                    currentAttract = createAttractFromNote(note, index, currentAttract);
                else
                    currentAttract.GetComponent<attractScript>().addNote(note);
            }
            if (i > 5000)
            {
                throw new System.Exception("Too many notes (max = 5000) or infinite loop in mapGenerationScript.generateAttracts()");
            }
            i++;
        }
        GeneralParameters.nbNotes = index - GeneralParameters.firstNote;
        GeneralParameters.isLevelReady = true;
    }

    GameObject createAttractFromNote(Note note, int index, GameObject prevAttract)
    {
        note.index = index;
        if (GeneralParameters.debug) print("Create attract from " + note);
        GameObject newAttract = (GameObject)GameObject.Instantiate(referenceAttract, new Vector3(0, 50, 0), Quaternion.identity);
        attractScript newAttractScript = newAttract.GetComponent<attractScript>();
        newAttractScript.instant = index - GeneralParameters.firstNote;
        newAttractScript.transformWithNote(note, prevAttract);

        if (referenceAttract.active)
        {
            referenceAttract.GetComponent<attractScript>().disable();
            referenceAttract.active = false;
        }
        newAttract.active = true;

        return newAttract;
    }

    void changeTempo(int tempo)
    {
        if(GeneralParameters.debug) print("New tempo : " + tempo);
        GeneralParameters.defaultTempo = Mathf.RoundToInt(tempo * GeneralParameters.relativeTempo);
    }
}